package com.gigi.service.manual;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cola.dto.MultiResponse;
import com.alibaba.cola.dto.Response;
import com.alibaba.cola.dto.SingleResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gigi.annotation.AuthCheck;
import com.gigi.common.Constant;
import com.gigi.common.IdRequest;
import com.gigi.entity.TeamEntity;
import com.gigi.entity.UserEntity;
import com.gigi.entity.UserTeamEntity;
import com.gigi.exception.BusinessException;
import com.gigi.mapper.manual.TeamManualMapper;
import com.gigi.model.dto.TeamDTO;
import com.gigi.model.enums.ErrorCodeEnum;
import com.gigi.model.enums.TeamStatusEnum;
import com.gigi.model.request.JoinTeamRequest;
import com.gigi.model.request.SearchTeamsRequest;
import com.gigi.model.vo.MemberVO;
import com.gigi.model.vo.TeamMemberVO;
import com.gigi.model.vo.TeamUserVO;
import com.gigi.service.generated.TeamService;
import com.gigi.service.generated.UserService;
import com.gigi.service.generated.UserTeamService;
import com.gigi.util.AuthorityUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 队伍管理
 *
 * @author Gigi
 */
@Slf4j
@Service
public class TeamManageService {

    @Autowired
    private TeamService teamService;

    @Autowired
    private UserTeamService userTeamService;

    @Autowired
    private UserService userService;

    @Autowired
    private TeamManualMapper teamManualMapper;

    @Autowired(required = false)
    private RedissonClient redissonClient;

    /**
     * 创建队伍接口
     *
     * @param teamDO
     * @param httpServletRequest
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Response createTeam(TeamDTO teamDO, HttpServletRequest httpServletRequest) {
        log.info("createTeam expireTime: {}", teamDO.getExpireTime());
        // 1、是否登录
        UserEntity loginUser = AuthorityUtil.getLoginUser(httpServletRequest);
        // 2、参数校验
        checkParamsForSaveTeam(teamDO);
        // 如果是加密，密码格式限制
        if (Objects.nonNull(teamDO.getTeamStatus()) && TeamStatusEnum.ENCRYPTED.getCode().equals(teamDO.getTeamStatus())) {
            if (!teamDO.getTeamPassword().matches("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,10}$")) {
                throw new BusinessException(ErrorCodeEnum.PARAM_NOT_MATCH);
            }
        }
        // 最多创建（包括加入的）5个队伍
        LambdaQueryWrapper<UserTeamEntity> wrapper1 = new LambdaQueryWrapper<UserTeamEntity>()
                .eq(UserTeamEntity::getUserId, loginUser.getId());
        if (userTeamService.count(wrapper1) >= 5) {
            throw new BusinessException(ErrorCodeEnum.JOIN_TEAM_LIMIT_EXCEEDED);
        }
        // 3、创建队伍
        TeamEntity teamEntity = new TeamEntity();
        BeanUtils.copyProperties(teamDO, teamEntity);
        teamEntity.setUserId(loginUser.getId());
        // 密码md5加密
        if (StrUtil.isNotBlank(teamEntity.getTeamPassword())) {
            String safetyPassword = DigestUtils.md5DigestAsHex((teamEntity.getTeamPassword() + Constant.SALT).getBytes());
            teamEntity.setTeamPassword(safetyPassword);
        }
        if (!teamService.save(teamEntity)) {
            throw new BusinessException(ErrorCodeEnum.SAVE_FAILED);
        }
        log.info("createTeam saved expireTime: {}", teamService.getById(teamEntity.getId()).getExpireTime());
        // 4、新增队伍用户关系数据
        UserTeamEntity userTeamEntity = new UserTeamEntity();
        userTeamEntity.setTeamId(teamEntity.getId());
        userTeamEntity.setUserId(loginUser.getId());
        userTeamEntity.setJoinTime(LocalDateTime.now());
        if (!userTeamService.save(userTeamEntity)) {
            throw new BusinessException(ErrorCodeEnum.SAVE_FAILED);
        }
        // 5、返回成功
        return Response.buildSuccess();
    }

    /**
     * 参数校验（创建 & 修改）
     *
     * @param teamDO
     */
    private void checkParamsForSaveTeam(TeamDTO teamDO) {
        // 队伍名称不能超过20个字符
        if (StrUtil.isBlank(teamDO.getTeamName()) || teamDO.getTeamName().length() > 20) {
            throw new BusinessException(ErrorCodeEnum.PARAM_NOT_MATCH);
        }
        // 队伍描述不能超过400个字符
        if (StrUtil.isBlank(teamDO.getTeamDescription()) || teamDO.getTeamDescription().length() > 400) {
            throw new BusinessException(ErrorCodeEnum.PARAM_NOT_MATCH);
        }
        // 人数3-10人
        if (teamDO.getMaxNum() < 3 || teamDO.getMaxNum() > 10) {
            throw new BusinessException(ErrorCodeEnum.PARAM_NOT_MATCH);
        }
        // 过期时间 > 当前时间
        if (Objects.nonNull(teamDO.getExpireTime()) && LocalDateTime.now().isAfter(teamDO.getExpireTime())) {
            throw new BusinessException(ErrorCodeEnum.PARAM_NOT_MATCH);
        }
    }

    /**
     * 搜索队伍接口
     *
     * @param request
     * @param httpServletRequest
     * @return
     */
    public MultiResponse<TeamUserVO> searchTeam(SearchTeamsRequest request, HttpServletRequest httpServletRequest) {
        // 1、是否登录
        UserEntity loginUser = AuthorityUtil.getLoginUser(httpServletRequest);
        // 2、查询
        LambdaQueryWrapper<TeamEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(TeamEntity::getId);
        wrapper.gt(TeamEntity::getExpireTime, LocalDateTime.now());
        if (StrUtil.isNotBlank(request.getKeyWord())) {
            wrapper.and(w -> w.like(TeamEntity::getTeamName, request.getKeyWord())
                    .or().like(TeamEntity::getTeamDescription, request.getKeyWord()));
        }
        Page<TeamEntity> teamEntityPage = teamService.page(new Page<>(request.getPageNum(), request.getPageSize()), wrapper);
        if (CollUtil.isEmpty(teamEntityPage.getRecords())) {
            return MultiResponse.ofWithoutTotal(Collections.emptyList());
        }
        // 3、转换
        List<TeamUserVO> teamUserVOS = new ArrayList<>();
        teamEntityPage.getRecords().forEach(e -> {
            TeamUserVO teamUserVO = new TeamUserVO();
            BeanUtils.copyProperties(e, teamUserVO);
            teamUserVO.setTeamId(e.getId());
            teamUserVOS.add(teamUserVO);
        });
        // 4、查队长信息
        List<UserEntity> userEntities = Collections.emptyList();
        List<Long> userIds = teamUserVOS.stream().map(TeamUserVO::getUserId).distinct().collect(Collectors.toList());
        if (CollUtil.isNotEmpty(userIds)) {
            LambdaQueryWrapper<UserEntity> userWrapper = new LambdaQueryWrapper<UserEntity>()
                    .select(UserEntity::getId, UserEntity::getUserName, UserEntity::getAvatarUrl)
                    .in(UserEntity::getId, userIds);
            userEntities = userService.list(userWrapper);
        }
        List<UserEntity> finalUserEntities = userEntities;
        teamUserVOS.forEach(e -> {
            // 5、查已加入人数
            LambdaQueryWrapper<UserTeamEntity> userTeamWrapper = new LambdaQueryWrapper<UserTeamEntity>()
                    .orderByAsc(UserTeamEntity::getId)
                    .eq(UserTeamEntity::getTeamId, e.getTeamId());
            List<UserTeamEntity> userTeamEntities = userTeamService.list(userTeamWrapper);
            e.setCurrentNum(userTeamEntities.size());
            // 6、查是否是队员
            if (!loginUser.getId().equals(e.getUserId())) {
                userTeamEntities.remove(0);
                userTeamEntities.stream().filter(ut -> ut.getUserId().equals(loginUser.getId())).findFirst().ifPresent(ut -> e.setIfMember(true));
            }
            // set 队长信息
            if (CollUtil.isNotEmpty(finalUserEntities)) {
                List<UserEntity> userEntityList =
                        finalUserEntities.stream().filter(u -> e.getUserId().equals(u.getId())).collect(Collectors.toList());
                e.setUserName(userEntityList.get(0).getUserName());
                e.setUserAvatar(userEntityList.get(0).getAvatarUrl());
            }
        });
        // 6、返回
        return MultiResponse.of(teamUserVOS, (int) teamEntityPage.getTotal());
    }

    /**
     * 修改队伍信息接口
     *
     * @param teamDO
     * @param httpServletRequest
     * @return
     */
    public Response editTeam(TeamDTO teamDO, HttpServletRequest httpServletRequest) {
        log.info("editTeam expireTime: {}", teamDO.getExpireTime());
        // 1、队伍id不能为空 & > 0
        if (Objects.isNull(teamDO.getId()) || teamDO.getId() <= 0) {
            throw new BusinessException(ErrorCodeEnum.PARAM_ERROR);
        }
        // 3、队伍是否存在
        TeamEntity team = teamService.getById(teamDO.getId());
        if (Objects.isNull(team)) {
            throw new BusinessException(ErrorCodeEnum.NO_DATA);
        }
        // 4、管理员 or 自己可以修改
        AuthorityUtil.isAdminOrSelf(httpServletRequest, team.getUserId());
        // 5、密码校验，分三种情况
        Integer oldStatus = team.getTeamStatus();
        Integer newStatus = teamDO.getTeamStatus();
        // （1）加密 =》 公开，清空密码
        if (TeamStatusEnum.ENCRYPTED.getCode().equals(oldStatus) && TeamStatusEnum.PUBLIC.getCode().equals(newStatus)) {
            teamDO.setTeamPassword(StrUtil.EMPTY);
        }
        // （2）公开 =》加密，密码不能为空 & 格式限制
        String format = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,10}$";
        if (TeamStatusEnum.PUBLIC.getCode().equals(oldStatus) && TeamStatusEnum.ENCRYPTED.getCode().equals(newStatus)) {
            if (StrUtil.isBlank(teamDO.getTeamPassword()) || !teamDO.getTeamPassword().matches(format)) {
                throw new BusinessException(ErrorCodeEnum.PARAM_NOT_MATCH);
            }
            teamDO.setTeamPassword(DigestUtils.md5DigestAsHex((teamDO.getTeamPassword() + Constant.SALT).getBytes()));
        }
        // （3）加密 =》加密 & 新旧密码不为空 => 改密码
        if (TeamStatusEnum.ENCRYPTED.getCode().equals(oldStatus) && TeamStatusEnum.ENCRYPTED.getCode().equals(newStatus)) {
            if (StrUtil.isNotBlank(teamDO.getOldPassword()) && (StrUtil.isNotBlank(teamDO.getNewPassword()))) {
                checkForChangePwd(teamDO.getOldPassword(), teamDO.getNewPassword(), team.getTeamPassword());
                teamDO.setTeamPassword(DigestUtils.md5DigestAsHex((teamDO.getNewPassword() + Constant.SALT).getBytes()));
            }
        }
        // 6、其他参数校验
        checkParamsForSaveTeam(teamDO);
        // 6、修改
        TeamEntity teamEntity = new TeamEntity();
        BeanUtils.copyProperties(teamDO, teamEntity);
        if (!teamService.updateById(teamEntity)) {
            throw new BusinessException(ErrorCodeEnum.EDIT_FAILED);
        }
        log.info("editTeam updated expireTime: {}", teamService.getById(teamEntity.getId()).getExpireTime());
        // 7、返回成功
        return Response.buildSuccess();
    }

    /**
     * 修改密码校验
     *
     * @param oldPassword
     * @param newPassword
     * @param confirmPassword
     */
    private void checkForChangePwd(String oldPassword, String newPassword, String confirmPassword) {
        if (StrUtil.isBlank(confirmPassword)) {
            throw new BusinessException(ErrorCodeEnum.NO_DATA);
        }
        // 新旧密码不能相同
        if (oldPassword.equals(newPassword)) {
            throw new BusinessException(ErrorCodeEnum.PARAM_NOT_MATCH);
        }
        // 新旧密码格式校验
        String format = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,10}$";
        if (!oldPassword.matches(format) || !newPassword.matches(format)) {
            throw new BusinessException(ErrorCodeEnum.PARAM_NOT_MATCH);
        }
        // 旧密码校验
        if (!confirmPassword.equals(DigestUtils.md5DigestAsHex((oldPassword + Constant.SALT).getBytes()))) {
            throw new BusinessException(ErrorCodeEnum.OLD_PASSWORD_ERROR);
        }
    }

    /**
     * 解散队伍接口
     *
     * @param request
     * @param httpServletRequest
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Response disbandTeam(IdRequest request, HttpServletRequest httpServletRequest) {
        // 1、队伍是否存在
        TeamEntity team = teamService.getById(request.getId());
        if (Objects.isNull(team)) {
            throw new BusinessException(ErrorCodeEnum.NO_DATA);
        }
        // 2、本人可以解散
        AuthorityUtil.isSelf(httpServletRequest, team.getUserId());
        // 3、删队伍表
        if (!teamService.removeById(request.getId())) {
            throw new BusinessException(ErrorCodeEnum.DELETE_FAILED);
        }
        // 4、删关系表
        UserTeamEntity userTeamEntity = new UserTeamEntity();
        userTeamEntity.setTeamId(request.getId());
        LambdaQueryWrapper<UserTeamEntity> wrapper = new LambdaQueryWrapper<>(userTeamEntity);
        if (!userTeamService.remove(wrapper)) {
            throw new BusinessException(ErrorCodeEnum.DELETE_FAILED);
        }
        return Response.buildSuccess();
    }

    /**
     * 加入队伍接口
     *
     * @param request
     * @param httpServletRequest
     * @return
     */
    public Response joinTeam(JoinTeamRequest request, HttpServletRequest httpServletRequest) {
        // redisson 分布式锁
        // (1) 获取锁
        RLock lock = Objects.nonNull(redissonClient) ? redissonClient.getLock(Constant.JOIN_TEAM_LOCK) : null;
        // (2) 如果加锁成功，执行写缓存操作
        try {
            boolean tryLock = Objects.nonNull(lock) && lock.tryLock(15, -1, TimeUnit.MILLISECONDS);

            if (Objects.isNull(redissonClient) || tryLock) {
                if (Objects.isNull(redissonClient)) {
                    log.warn("joinTeam 未配置 redissonClient，无法使用分布式锁");
                }
                if (tryLock) {
                    log.info("joinTeam 加锁成功" + Thread.currentThread().getName());
                }
                // 1、是否登录
                UserEntity loginUser = AuthorityUtil.getLoginUser(httpServletRequest);
                // 校验
                checkConditionForJoinTeam(request, loginUser);
                // 9、插入关系表
                UserTeamEntity userTeamEntity = new UserTeamEntity();
                userTeamEntity.setTeamId(request.getId());
                userTeamEntity.setUserId(loginUser.getId());
                userTeamEntity.setJoinTime(LocalDateTime.now());
                if (!userTeamService.save(userTeamEntity)) {
                    throw new BusinessException(ErrorCodeEnum.SAVE_FAILED);
                }

            } else {
                log.info("joinTeam 加锁失败" + Thread.currentThread().getName());
            }
        } catch (InterruptedException e) {
            log.error("joinTeam 加锁失败", e);
        } finally {
            // (3) 只释放自己的锁
            if (Objects.nonNull(lock) && lock.isHeldByCurrentThread()) {
                log.info("joinTeam 释放锁" + Thread.currentThread().getName());
                lock.unlock();
            }
        }
        // 10、返回成功
        return Response.buildSuccess();
    }

    /**
     * 校验是否满足加入队伍条件
     *
     * @param request
     * @param loginUser
     */
    private void checkConditionForJoinTeam(JoinTeamRequest request, UserEntity loginUser) {
        // 2、队伍是否存在
        TeamEntity team = teamService.getById(request.getId());
        if (Objects.isNull(team)) {
            throw new BusinessException(ErrorCodeEnum.NO_DATA);
        }
        // 3、不能加入自己创建的队伍
        if (team.getUserId().equals(loginUser.getId())) {
            throw new BusinessException(ErrorCodeEnum.CANNOT_JOIN_SELF_TEAM);
        }
        // 4、队伍是否已过期
        if (team.getExpireTime().isBefore(LocalDateTime.now())) {
            throw new BusinessException(ErrorCodeEnum.TEAM_EXPIRED);
        }
        // 5、队伍如果是加密，校验密码是否正确
        if (TeamStatusEnum.ENCRYPTED.getCode().equals(team.getTeamStatus())) {
            if (StrUtil.isBlank(request.getPassword()) || !team.getTeamPassword().equals(DigestUtils.md5DigestAsHex((request.getPassword() + Constant.SALT).getBytes()))) {
                throw new BusinessException(ErrorCodeEnum.PASSWORD_ERROR);
            }
        }
        // 查出该队伍所有加入列表
        List<UserTeamEntity> userTeamEntities = getUserTeamEntities(request.getId());
        // 大于1，说明除了队长有人加入了
        if (userTeamEntities.size() > 1) {
            // 6、队伍是否满员
            if (userTeamEntities.size() >= team.getMaxNum()) {
                throw new BusinessException(ErrorCodeEnum.TEAM_FULL);
            }
            // 7、是否已经加入过队伍
            long count = userTeamEntities.stream().filter(e -> loginUser.getId().equals(e.getUserId())).count();
            if (count > 0) {
                throw new BusinessException(ErrorCodeEnum.ALREADY_JOINED);
            }
        }
        // 8、最多加入（包括创建的）5个队伍
        LambdaQueryWrapper<UserTeamEntity> wrapper1 = new LambdaQueryWrapper<UserTeamEntity>()
                .eq(UserTeamEntity::getUserId, loginUser.getId());
        if (userTeamService.count(wrapper1) >= 5) {
            throw new BusinessException(ErrorCodeEnum.JOIN_TEAM_LIMIT_EXCEEDED);
        }
    }

    /**
     * 获取队伍所有加入列表
     *
     * @param teamId
     * @return
     */
    private List<UserTeamEntity> getUserTeamEntities(Long teamId) {
        LambdaQueryWrapper<UserTeamEntity> wrapper = new LambdaQueryWrapper<UserTeamEntity>()
                .orderByAsc(UserTeamEntity::getId)
                .eq(UserTeamEntity::getTeamId, teamId);
        List<UserTeamEntity> userTeamEntities = userTeamService.list(wrapper);
        return userTeamEntities;
    }

    /**
     * 退出队伍接口
     *
     * @param request
     * @param httpServletRequest
     * @return
     */
    public Response quitTeam(IdRequest request, HttpServletRequest httpServletRequest) {
        // 1、队伍是否存在
        TeamEntity team = teamService.getById(request.getId());
        if (Objects.isNull(team)) {
            throw new BusinessException(ErrorCodeEnum.NO_DATA);
        }
        // 查出该队伍所有加入列表
        List<UserTeamEntity> userTeamEntities = getUserTeamEntities(request.getId());
        // 2、是否已加入队伍（是否本人）
        UserEntity loginUser = AuthorityUtil.getLoginUser(httpServletRequest);
        Long loginUserId = loginUser.getId();
        List<UserTeamEntity> selfList =
                userTeamEntities.stream().filter(e -> e.getUserId().equals(loginUserId)).collect(Collectors.toList());
        if (selfList.size() < 1) {
            throw new BusinessException(ErrorCodeEnum.ACCESS_DENIED);
        }
        // 3、如果就剩自己，解散队伍（删队伍表）
        if (userTeamEntities.size() == 1) {
            if (!teamService.removeById(request.getId())) {
                throw new BusinessException(ErrorCodeEnum.DELETE_FAILED);
            }
        } else {
            // 4、如果还有别人 & 队长退出，顺位队长身份
            if (loginUserId.equals(team.getUserId())) {
                // 找出新队长userId
                List<Long> userIds = userTeamEntities.stream().map(UserTeamEntity::getUserId).collect(Collectors.toList());
                Long newLeaderUserId = userIds.get(1);
                // 修改队伍表
                TeamEntity teamEntity = new TeamEntity();
                teamEntity.setId(team.getId());
                teamEntity.setUserId(newLeaderUserId);
                if (!teamService.updateById(teamEntity)) {
                    throw new BusinessException(ErrorCodeEnum.EDIT_FAILED);
                }
            }
        }
        // 5、删关系表
        List<Long> delIds = selfList.stream().map(UserTeamEntity::getId).collect(Collectors.toList());
        if (!userTeamService.removeByIds(delIds)) {
            throw new BusinessException(ErrorCodeEnum.DELETE_FAILED);
        }
        return Response.buildSuccess();
    }

    /**
     * 根据id获取队伍接口
     *
     * @param request
     * @param httpServletRequest
     * @return
     */
    public SingleResponse<TeamDTO> getTeamById(IdRequest request, HttpServletRequest httpServletRequest) {
        // 1、查询
        TeamEntity teamEntity = teamService.getById(request.getId());
        if (Objects.isNull(teamEntity)) {
            throw new BusinessException(ErrorCodeEnum.NO_DATA);
        }
        // 2、鉴权
        AuthorityUtil.isAdminOrSelf(httpServletRequest, teamEntity.getUserId());
        // 3、转换
        TeamDTO teamDTO = new TeamDTO();
        BeanUtils.copyProperties(teamEntity, teamDTO);
        // 4、脱敏
        teamDTO.setTeamPassword(null);
        // 5、返回
        return SingleResponse.of(teamDTO);
    }

    /**
     * 我的队伍接口
     *
     * @param httpServletRequest
     * @return
     */
    public MultiResponse<TeamUserVO> myTeam(HttpServletRequest httpServletRequest) {
        // 1、是否登录
        UserEntity loginUser = AuthorityUtil.getLoginUser(httpServletRequest);
        // 2、查询
        List<TeamUserVO> myTeams = teamManualMapper.getMyTeams(loginUser.getId());
        // 3、查询已加入人数
        if (CollUtil.isNotEmpty(myTeams)) {
            List<Long> teamIds = myTeams.stream().map(TeamUserVO::getTeamId).collect(Collectors.toList());
            LambdaQueryWrapper<UserTeamEntity> userTeamWrapper = new LambdaQueryWrapper<UserTeamEntity>()
                    .select(UserTeamEntity::getTeamId)
                    .in(UserTeamEntity::getTeamId, teamIds);
            List<UserTeamEntity> list = userTeamService.list(userTeamWrapper);
            Map<Long, List<UserTeamEntity>> map = list.stream().collect(Collectors.groupingBy(UserTeamEntity::getTeamId));
            myTeams.forEach(vo -> {
                vo.setCurrentNum(map.get(vo.getTeamId()).size());
            });
        }
        return MultiResponse.ofWithoutTotal(myTeams);
    }

    /**
     * 队员列表接口
     *
     * @param request
     * @param httpServletRequest
     * @return
     */
    @AuthCheck
    public SingleResponse<TeamMemberVO> memberList(IdRequest request, HttpServletRequest httpServletRequest) {
        // 1、队伍是否存在
        TeamEntity teamEntity = teamService.getById(request.getId());
        if (Objects.isNull(teamEntity)) {
            throw new BusinessException(ErrorCodeEnum.NO_DATA);
        }
        // 2、查询
        List<MemberVO> members = teamManualMapper.getMemberList(request.getId());
        // 3、转换
        TeamMemberVO teamMemberVO = new TeamMemberVO();
        BeanUtils.copyProperties(teamEntity, teamMemberVO);
        teamMemberVO.setMembers(members);
        // 4、返回
        return SingleResponse.of(teamMemberVO);
    }

}
